package cn.tedu.reflection;

import com.sun.media.jfxmediaimpl.HostUtils;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/*
Author     :Dsi
Date       : 2021/11/23 10:37
Description: 该类用于测试反射技术的测试类
*/
public class TestReflect {
    /*单元测试方法：是Java中最小的测试单元，使用灵活
     * 语法要求：public + void + 没有参数 + @Test
     * 注意：使用时需要导包：Add junit4 to classpath
     * 导包以后的效果：import org.junit.Test;*/
    /*测试1.通过单元测试方法，获取目标类Student对应的字节码对象(Class)*/
    @Test
    public void getClazz() throws ClassNotFoundException {
        Class<?> clazz1=Class.forName("cn.tedu.reflection.Student");
        Class<?> clazz2=Student.class;
        Class<?> calzz3 = new Student().getClass();
        //直接打印字节码对象，注意前面有个class，这是 一个对象
        System.out.println(clazz1);
        //通过字节码对象获取的目标类Student的全路径名
        System.out.println(clazz2.getName());
        //通过字节码对象，获取目标类的类名
        System.out.println(clazz1.getSimpleName());
        ////通过字节码对象，获取目标类的包对象
        System.out.println(calzz3.getPackage());
        //通过字节码对象，获取目标类包对象，在通过包对象获取包的全路径
        System.out.println(calzz3.getPackage().getName());
    }

    /*测试2：通过反射技术，获取目标类的成员对象(Field)*/
    @Test
    public void getFie() throws ClassNotFoundException {

        Class a=Student.class;
        Class<?> a2 = new Student().getClass();
        Class<?> a3=Class.forName("cn.tedu.reflection.Student");
        Field[] fs=a.getFields();
        System.out.println(fs);
        //Field获取的是字段，只能获取到通过public修饰符的成员变量
        System.out.println(Arrays.toString(fs));
        //3.遍历数组，获取每个字段对象
        for (Field f:fs
             ) {
            //通过本轮循环的字段对象，进一步获取字段的名字与字段的类型
            System.out.println(f);
            System.out.println(f.getName());
        }
    }

    /*测试3.通过单元测试方法，练习引用类型数组的定义与遍历*/
    @Test
    public void getSu(){
        Class<?> a = new Student().getClass();
        Student s1=new Student("aa",45);
        Student s2=new Student("bb",46);
        Student s3=new Student("cc",47);

        Student[] ss={s1,s2,s3};
        System.out.println(Arrays.toString(ss));
        for (Student sss:ss
             ) {
            System.out.println(sss);
            sss.eat(4);
            System.out.println(sss.age);
        }
    }

    /*测试4.通过反射技术，获取目标类的成员方法(Fuction)*/
    @Test
    public void getFuction(){
        Class<?> c=Student.class;
        Method[] m = c.getMethods();//通过字节码对象获取目标类中的成员类
        for (Method s:m
             ) {
            System.out.println(s);//获取方法对象
            System.out.println(s.getName());//获取方法名
            Class<?>[] cc = s.getParameterTypes();
            System.out.println(Arrays.toString(cc));
        }
    }

    /*测试5.通过反射技术，获取目标对象的构造方法(Constructor)*/
    @Test
    public void getCons(){
        Class<?> c=new Student().getClass();
        Constructor<?>[] cs = c.getConstructors();
        for (Constructor s:cs
             ) {
            System.out.println(s);//构造函数对象
            System.out.println(s.getName());//构造函数名字
            Class[] cs1 = s.getParameterTypes();
            System.out.println(Arrays.toString(cs1));//参数类型
        }



    }
    /*测试6.通过反射技术，创建目标类Student的对象*/
    @Test
    public void getObject() throws Exception {
        Class<?> c=Class.forName("cn.tedu.reflection.Student");
        /*反射创建对象的方案1：通过字节码对象触发目标中的无参构造来创建对象*/
        Object o = c.newInstance();//通过字节码对象，创建目标类对象
        System.out.println(o);
        /*反射创建对象的方案2：通过字节码对象触发目标中的其他含参构造来创建对象
        * 思路：
        * 1.先获取指定的构造函数对象，注意：传入特定的构造函数，传入的是字节码对象
        * 2.通过刚刚获取到的构造函数对象来创建目标类Student的对象*/
        //3.获取目标类中指定的全参构造
        //System.out.println(Arrays.toString(c.getConstructors()));
        Constructor<?> cc = c.getConstructor(String.class,int.class);
        //4.通过刚刚获取到的构造函数对象来创建目标类的对象
        Object l = cc.newInstance("l", 6);
        System.out.println(l);
        /*测试6.2*/
        Constructor<?> ccc = c.getConstructor(String.class);
        Object o1 = ccc.newInstance("45");
        System.out.println(o1);
    }
}















